/**
 * Copyright (c) 2015, 玛雅牛［李飞］ (myaniu@gmail.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jfinal.plugin.zbus;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import com.jfinal.kit.HashKit;

import io.zbus.kit.JsonKit;
import io.zbus.mq.Message;
import io.zbus.mq.MessageHandler;
import io.zbus.mq.MqClient;

/**
 * @ClassName: TMsgHandler
 * @Description: 泛型消息回调接口（自动转型）
 * @author 李飞
 * @date 2015年8月2日 上午1:27:46
 * @since V1.0.0
 */
public abstract class TMsgHandler<T> implements MessageHandler {
    /**
     * 范型类型
     */
    private final Class<T> tClass;

    /**
     * tag
     */
    private String tag = null;

    /**
     * <p>
     * Title: TMsgHandler
     * </p>
     * <p>
     * Description: 构造函数
     * </p>
     *
     * @since V1.0.0
     */
    public TMsgHandler() {
        tClass = this.getSuperClassGenricType();
        this.tag = HashKit.md5(tClass.getName()).substring(8, 24);
    }

    String getTag() {
        return this.tag;
    }

    @Override
    public final void handle(Message msg, MqClient client) throws IOException {
        //tag不同，则直接略过
        if (!this.tag.equals(msg.getTag())) {
            return;
        }
        T obj = JsonKit.parseObject(msg.getBodyString(), tClass);
        this.handle((T) obj);
    }

    /**
     * @Title: handle
     * @Description: 消费者收到消息后的处理函数，子类需实现此方法
     * @param msg
     *            收到的消息
     * @since V1.0.0
     */
    public abstract void handle(T msg);

    @SuppressWarnings("unchecked")
    private Class<T> getSuperClassGenricType() {
        Class<?> clazz = this.getClass();
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            throw new RuntimeException(clazz.getSimpleName() + "'s superclass not ParameterizedType");
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        if (!(params[0] instanceof Class)) {
            throw new RuntimeException(
                    clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
        }
        return (Class<T>) params[0];
    }
}
